package org.example.service.impl;

import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.apache.rocketmq.spring.support.RocketMQHeaders;
import org.example.mapper.AccountInfoMapper;
import org.example.model.message.AccountChangeMessage;
import org.example.service.AccountInfoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;

/**
 * @author shenguangyang
 */
@Service
public class AccountInfoServiceImpl implements AccountInfoService {
    private static final Logger log = LoggerFactory.getLogger(AccountInfoServiceImpl.class);

    @Resource
    private RocketMQTemplate rocketMQTemplate;

    @Resource
    private AccountInfoMapper accountInfoMapper;

    @Override
    public void sendUpdateAccountBalance(AccountChangeMessage accountChangeMessage) {
        // 发送消息
        Message<AccountChangeMessage> messageFinal = MessageBuilder
                .withPayload(accountChangeMessage)
                .setHeader(RocketMQHeaders.TRANSACTION_ID, accountChangeMessage.getMsgId())
                .build();
        String destination = "topic_txmsg";
        // log.info("成功发送消息,消息内容为:{},返回值为:{}", message, result);
        SendResult sendResult = rocketMQTemplate.sendMessageInTransaction(destination, messageFinal,null);
        log.info("send message body = {}, result = {}", accountChangeMessage, sendResult.getSendStatus());
    }

    @Transactional
    @Override
    public void doUpdateAccountBalance(AccountChangeMessage accountChangeMessage) {
        log.info("开始更新本地事务，事务号:{}", accountChangeMessage.getMsgId());
        // accountChangeMessage.getAmount().negate() 将正数变成负数
        int result = accountInfoMapper.updateAccountBalance("1", accountChangeMessage.getAmount().negate());
        if (result == 0) {
            throw new RuntimeException("账号不存在或者余额不足");
        }

        // 为幂等作准备
        accountInfoMapper.addTx(accountChangeMessage.getMsgId());
        log.info("结束更新本地事务, 事务号:{}", accountChangeMessage.getMsgId());
        if (accountChangeMessage.getAmount().compareTo(new BigDecimal(50)) == 0) {
            throw new RuntimeException("bank1更新本地事务时抛出异常");
        }
    }
}
